package com.cosmoplat.xikai.business.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cosmoplat.xikai.business.config.producLine.LocationConfig;
import com.cosmoplat.xikai.business.domain.BaseDeliveryInfo;
import com.cosmoplat.xikai.business.domain.BaseDispatchTask;
import com.cosmoplat.xikai.business.domain.BaseSafetyStock;
import com.cosmoplat.xikai.business.domain.mes.req.MesMaterialDistributionRequest;
import com.cosmoplat.xikai.business.domain.vo.AlarmVo;
import com.cosmoplat.xikai.business.enums.MaterialEnum;
import com.cosmoplat.xikai.business.service.*;
import com.cosmoplat.xikai.business.mapper.BaseSafetyStockMapper;
import com.cosmoplat.xikai.common.enums.business.AlarmTypeEnum;
import com.cosmoplat.xikai.common.utils.DateUtils;
import com.cosmoplat.xikai.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 22047582
 * @description 针对表【base_safety_stock】的数据库操作Service实现
 * @createDate 2025-01-07 13:51:30
 */
@Slf4j
@Service
public class BaseSafetyStockServiceImpl extends ServiceImpl<BaseSafetyStockMapper, BaseSafetyStock> implements BaseSafetyStockService {

    @Autowired
    private BaseDispatchTaskService taskService;

    @Autowired
    private BaseDeliveryInfoService deliveryInfoService;

    @Autowired
    private BaseAlarmRecordService alarmRecordService;

    @Autowired
    private MesRequestService mesRequestService;

    @Autowired
    private DeviceCallService deviceCallService;

    @Autowired
    private LocationConfig locationConfig;

    @Value("${device.code}")
    private String deviceCode;

    @Async
    @Override
    public void checkSafetyStock() {

        // 查询已配置的安全库存配置
        List<BaseSafetyStock> safetyStockList = list();
        if (CollectionUtils.isEmpty(safetyStockList)) {
            log.warn("全部物料未设置安全库存");
            return;
        }
        BaseDispatchTask doingTask = taskService.getDoingTask();
        if (doingTask == null) {
            log.info("没有进行中的任务，不进行安全库存检查");
            return;
        }
        Map<String, BaseSafetyStock> safetyStockMap = safetyStockList.stream().collect(Collectors.toMap(BaseSafetyStock::getMaterialCode, Function.identity()));
        List<BaseDeliveryInfo> deliveryInfoList = deliveryInfoService.getListByTaskId(doingTask.getTaskId());
        for (BaseDeliveryInfo deliveryInfo : deliveryInfoList) {
            if (!safetyStockMap.containsKey(deliveryInfo.getMaterialCode())) {
                log.info("物料：{} 未设置安全库存", deliveryInfo.getMaterialCode());
                continue;
            }
            BaseSafetyStock safetyStock = safetyStockMap.get(deliveryInfo.getMaterialCode());
            // 获取物料的库存数量
            BigDecimal stockQty = new BigDecimal(0);
            // 获取物料的库存数量 - 产线控制的库存 (法兰和绝缘轴)
            if (MaterialEnum.inStockMaterial(deliveryInfo.getMaterialCode())) {
                stockQty = deliveryInfo.getStockQty();
                if (stockQty == null) {
                    log.info("物料：{} 获取的库存数量为空, 未人工设置库存", deliveryInfo.getMaterialCode());
                    stockQty = BigDecimal.ZERO;
                }
            } else {
                // 设备上读取库存
                String materialCodeValue = deviceCallService.getMaterialCodeValue(deviceCode, deliveryInfo.getMaterialCode());
                if (StringUtils.isBlank(materialCodeValue)) {
                    log.warn("物料：{}, 获取的数量为空", deliveryInfo.getMaterialCode());
                    continue;
                }
                stockQty = new BigDecimal(materialCodeValue);
            }
            deliveryInfo.setStockQty(stockQty);
            // 库存数 小于 安全库存数
            if (stockQty.compareTo(safetyStock.getBaseSafetyStockQty()) < 0) {
                log.debug("物料：{} 安全库存不足，当前库存：{}，安全库存：{}", safetyStock.getMaterialCode(), deliveryInfo.getStockQty(), safetyStock.getBaseSafetyStockQty());
                // 缺料标识
                deliveryInfo.setShortage(1);
                // 已存在告警记录，不重复告警
                if (CollectionUtils.isNotEmpty(alarmRecordService.getAlarmingByMaterialCode(deliveryInfo.getMaterialCode(), AlarmTypeEnum.MISSING_MATERIAL))) {
                    log.debug("物料：{} 已存在告警记录，不重复告警", safetyStock.getMaterialCode());
                    continue;
                }
                // 触发安全库存告警
                AlarmVo alarmRecord = createAlarmRecord(deliveryInfo, safetyStock);

                // 调用mes,告警触发 25-9-8 mes&项目经理确认 缺料告警不触发mes
                // callMesAlarm(doingTask, alarmRecord, deliveryInfo);
                // 调用mes, 叫料
                callMesMaterial(doingTask, deliveryInfo, alarmRecord);
            } else {
                log.debug("物料：{} 安全库存充足，当前库存：{}，安全库存：{}", safetyStock.getMaterialCode(), deliveryInfo.getStockQty(), safetyStock.getBaseSafetyStockQty());
                // 检查是否存在缺料标志
                if (deliveryInfo.getShortage() == null || deliveryInfo.getShortage() == 1) {
                    // 删除缺料标识
                    deliveryInfo.setShortage(0);
                }
                // 关闭告警
                alarmRecordService.stopAlarm(doingTask, deliveryInfo.getMaterialCode(), AlarmTypeEnum.MISSING_MATERIAL, null);

            }
            // 更新库存数量
            deliveryInfoService.updateById(deliveryInfo);

        }

    }

    @Override
    public List<BaseSafetyStock> getSafetyStockList() {
        return list();
    }

    /**
     * 缺料 - 调用mes
     *
     * @param doingTask
     * @param deliveryInfo
     * @param alarmRecord
     * @date 17:05 2025/1/13
     **/
    private void callMesMaterial(BaseDispatchTask doingTask, BaseDeliveryInfo deliveryInfo, AlarmVo alarmRecord) {
        MesMaterialDistributionRequest distribution = new MesMaterialDistributionRequest();
        distribution.setCode(doingTask.getTaskNo());
        distribution.setOrderID(doingTask.getWorkOrderNo());
        distribution.setTaskID(doingTask.getTaskId());
        distribution.setDeliveryType(MesMaterialDistributionRequest.DeliveryTypeEnum.DELIVERY.getCode());
        // 未完成的产品数量
        BigDecimal unFinishedProductQty = new BigDecimal(0);
        if (doingTask.getCompletedQty() == null) {
            unFinishedProductQty = doingTask.getDispatchQty();
        } else {
            unFinishedProductQty = doingTask.getDispatchQty().subtract(doingTask.getCompletedQty());
        }
        // 配送数量 = 物料需求数量 * 未完成的产品数量
        distribution.setQuantity(deliveryInfo.getRequiredQty().multiply(unFinishedProductQty));

        distribution.setMaterial(deliveryInfo.getMaterialCode());
        distribution.setCreator(doingTask.getOperator());

        distribution.setEndLocation(locationConfig.getReceive());
        distribution.setCreateTime(new Date());
        distribution.setLastModifiedTime(new Date());
        mesRequestService.materialDistribution(distribution);
    }

    /**
     * mes告警
     *
     * @param doingTask
     * @param alarmRecord
     * @param deliveryInfo
     * @date 16:44 2025/1/13
     **/
    private void callMesAlarm(BaseDispatchTask doingTask, AlarmVo alarmRecord, BaseDeliveryInfo deliveryInfo) {
        alarmRecordService.shortMaterialCallMes(doingTask, deliveryInfo, alarmRecord);
    }

    /**
     * 创建告警记录
     *
     * @param deliveryInfo
     * @param safetyStock
     * @date 16:34 2025/1/13
     **/
    private AlarmVo createAlarmRecord(BaseDeliveryInfo deliveryInfo, BaseSafetyStock safetyStock) {
        AlarmVo alarmVo = new AlarmVo();
        alarmVo.setEquipmentCode(deviceCode);
        alarmVo.setAlarmCode(DateUtils.dateTimeNow());
        alarmVo.setAlarmName(deliveryInfo.getMaterialCode() + "安全库存不足");
        alarmVo.setAlarmType(AlarmTypeEnum.MISSING_MATERIAL.getCode());
        alarmVo.setAlarmContent(deliveryInfo.getMaterialCode() + "安全库存不足，当前库存：" + deliveryInfo.getStockQty() + ",安全库存：" + safetyStock.getBaseSafetyStockQty());
        alarmVo.setAlarmStartTime(new Date());
        alarmVo.setMaterialCode(deliveryInfo.getMaterialCode());
        AlarmVo alarmVo1 = alarmRecordService.createAlarmVo(alarmVo);
        return alarmVo1;
    }
}




